package service

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	"usbipproxy/domain/vo"
)

type UsbidsServiceImpl struct {
	usbMap    map[uint16]map[uint16]*vo.USBDeviceInfo
	usbMapMu  sync.RWMutex
	cacheOnce sync.Once
}

func (impl *UsbidsServiceImpl) GetUsbidsInfo(vid, pid string) (*vo.USBDeviceInfo, error) {
	vidUint, err := impl.hexStringToUint16(vid)
	if err != nil {
		return nil, fmt.Errorf("invalid VID: %v", err)
	}

	pidUint, err := impl.hexStringToUint16(pid)
	if err != nil {
		return nil, fmt.Errorf("invalid PID: %v", err)
	}

	return impl.getUSBDeviceInfo(vidUint, pidUint)
}

func NewUsbidsServiceImpl() UsbidsService {
	return &UsbidsServiceImpl{}
}

// 获取可能的 usb.ids 文件路径
func (impl *UsbidsServiceImpl) getUSBIDSPaths() []string {
	ex, err := os.Executable()
	if err != nil {
		panic(err)
	}

	// 获取可执行文件所在的目录
	exPath := filepath.Dir(ex)
	localFilePath := filepath.Join(exPath, "usb.ids")
	return []string{
		localFilePath,
		"/usr/share/hwdata/usb.ids",   // Fedora/CentOS/RHEL
		"/usr/share/usb.ids",          // Debian/Ubuntu
		"/usr/share/misc/usb.ids",     // Arch/Manjaro
		"/usr/share/usbutils/usb.ids", // OpenSUSE
		"/usr/local/share/usb.ids",    // 自定义安装位置
	}
}

// 查找 usb.ids 文件路径
func (impl *UsbidsServiceImpl) findUSBIDS() (string, error) {
	// 尝试从环境变量获取
	if path := os.Getenv("USB_IDS_PATH"); path != "" {
		if _, err := os.Stat(path); err == nil {
			return path, nil
		}
	}

	// 尝试标准位置
	for _, path := range impl.getUSBIDSPaths() {
		if _, err := os.Stat(path); err == nil {
			return path, nil
		}
	}

	// 尝试查找 usbutils 包的位置
	paths, _ := filepath.Glob("/var/lib/usbutils/usb.ids.*")
	if len(paths) > 0 {
		// 取最新版本
		return paths[len(paths)-1], nil
	}

	return "", fmt.Errorf("usb.ids file not found")
}

// 初始化USB ID映射
func (impl *UsbidsServiceImpl) initUSBMap() error {
	path, err := impl.findUSBIDS()
	if err != nil {
		return err
	}

	file, err := os.Open(path)
	if err != nil {
		return err
	}
	defer file.Close()

	impl.usbMap = make(map[uint16]map[uint16]*vo.USBDeviceInfo)
	currentVendor := uint16(0)

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()

		// 跳过注释和空行
		if len(line) == 0 || line[0] == '#' {
			continue
		}

		// 解析厂商行 (以4位十六进制开头)
		if len(line) > 4 && line[4] == ' ' {
			if vid, err := impl.parseHex(line[0:4]); err == nil {
				vendorName := strings.TrimSpace(line[5:])
				currentVendor = vid
				impl.usbMap[vid] = make(map[uint16]*vo.USBDeviceInfo)
				impl.usbMap[vid][0] = &vo.USBDeviceInfo{VendorName: vendorName}
			}
			continue
		}

		// 解析产品行 (以制表符+4位十六进制开头)
		if len(line) > 5 && line[0] == '\t' && line[1] != '\t' {
			if currentVendor != 0 {
				if pid, err := impl.parseHex(line[1:5]); err == nil {
					productName := strings.TrimSpace(line[6:])
					if _, exists := impl.usbMap[currentVendor]; exists {
						impl.usbMap[currentVendor][pid] = &vo.USBDeviceInfo{
							VendorName:  impl.usbMap[currentVendor][0].VendorName,
							ProductName: productName,
						}
					}
				}
			}
			continue
		}

		// 解析子产品行 (双制表符开头，可选实现)
	}

	return scanner.Err()
}

// 解析十六进制字符串 (支持0x前缀或无前缀)
func (impl *UsbidsServiceImpl) parseHex(s string) (uint16, error) {
	s = strings.TrimSpace(s)

	// 支持0x前缀
	if len(s) > 2 && strings.ToLower(s[0:2]) == "0x" {
		s = s[2:]
	}

	value, err := strconv.ParseUint(s, 16, 16)
	return uint16(value), err
}

// 确保只初始化一次映射
func (impl *UsbidsServiceImpl) ensureMapInitialized() error {
	var err error
	impl.cacheOnce.Do(func() {
		err = impl.initUSBMap()
	})
	return err
}

// 通过VID/PID获取设备信息
func (impl *UsbidsServiceImpl) getUSBDeviceInfo(vid, pid uint16) (*vo.USBDeviceInfo, error) {
	if err := impl.ensureMapInitialized(); err != nil {
		return nil, err
	}

	impl.usbMapMu.RLock()
	defer impl.usbMapMu.RUnlock()

	// 查找厂商
	vendorMap, vendorExists := impl.usbMap[vid]
	if !vendorExists {
		return &vo.USBDeviceInfo{
			VendorName:  fmt.Sprintf("Unknown Vendor (0x%04X)", vid),
			ProductName: fmt.Sprintf("Unknown Product (0x%04X)", pid),
		}, nil
	}

	// 查找产品
	if productInfo, productExists := vendorMap[pid]; productExists {
		return productInfo, nil
	}

	// 产品未找到
	return &vo.USBDeviceInfo{
		VendorName:  vendorMap[0].VendorName,
		ProductName: fmt.Sprintf("Unknown Product (0x%04X)", pid),
	}, nil
}

// 通过字符串格式的VID/PID获取
func (impl *UsbidsServiceImpl) GetUSBDeviceInfoFromString(vidStr, pidStr string) (*vo.USBDeviceInfo, error) {
	vidUint, err := impl.hexStringToUint16(vidStr)
	if err != nil {
		return nil, fmt.Errorf("invalid VID: %v", err)
	}

	pidUint, err := impl.hexStringToUint16(pidStr)
	if err != nil {
		return nil, fmt.Errorf("invalid PID: %v", err)
	}

	return impl.getUSBDeviceInfo(vidUint, pidUint)
}

// 将十六进制字符串转为uint16
func (impl *UsbidsServiceImpl) hexStringToUint16(s string) (uint16, error) {
	s = strings.TrimSpace(s)

	// 去除常见前缀
	s = strings.TrimPrefix(s, "0x")
	s = strings.TrimPrefix(s, "0X")
	s = strings.TrimPrefix(s, "VID_")
	s = strings.TrimPrefix(s, "PID_")

	// 尝试直接解析
	value, err := strconv.ParseUint(s, 16, 16)
	if err == nil {
		return uint16(value), nil
	}

	// 尝试去掉非十六进制字符
	var cleanStr strings.Builder
	for _, r := range s {
		if (r >= '0' && r <= '9') || (r >= 'A' && r <= 'F') || (r >= 'a' && r <= 'f') {
			cleanStr.WriteRune(r)
		}
	}

	if cleanStr.Len() > 0 {
		value, err = strconv.ParseUint(cleanStr.String(), 16, 16)
		if err == nil {
			return uint16(value), nil
		}
	}

	return 0, fmt.Errorf("invalid hex format: %s", s)
}
